package principal;

// <editor-fold defaultstate="collapsed" desc="LIBRERIAS">                          
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
// </editor-fold>         

public class Cliente extends Observable {

    // <editor-fold defaultstate="collapsed" desc="ATRIBUTOS">                          
    private ObjectOutputStream salida;
    private ObjectInputStream entrada;
    private String mensaje = "";
    private String servidorChat;
    private Socket cliente;
    String msg = "-1";
// </editor-fold>         

    // <editor-fold defaultstate="collapsed" desc="CONSTRUCTOR">                          
    public Cliente(String host) {


        servidorChat = host; // establecer el servidor al que se va a conectar este cliente

        Runnable hilo = new Runnable() {
            @Override
            public void run() {
                ejecutarCliente();
            }
        };
        Thread h = new Thread(hilo);
        h.start();

    }
// </editor-fold>         

    // <editor-fold defaultstate="collapsed" desc="METODOS">                          
    public String getMsg() {
        return msg;
    }
    // conectarse al servidor y procesar mensajes del servidor

    void ejecutarCliente() {
        // conectarse al servidor, obtener flujos, procesar la conexión
        try {
            conectarAServidor(); // Paso 1: crear un socket para realizar la conexión
            obtenerFlujos();      // Paso 2: obtener los flujos de entrada y salida
            procesarConexion(); // Paso 3: procesar la conexión
        } // el servidor cerró la conexión
        catch (EOFException excepcionEOF) {
            JOptionPane.showMessageDialog(null, "El cliente ha cerrado");
        } // procesar los problemas que pueden ocurrir al comunicarse con el servidor
        catch (IOException excepcionES) {
            JOptionPane.showMessageDialog(null, "El sevidor ha perdido");
            System.exit(0);
        } finally {
            cerrarConexion(); // Paso 4: cerrar la conexión
        }

    } // fin del método ejecutarCliente

    // conectarse al servidor
    private void conectarAServidor() throws IOException {
        mostrarMensaje("Intentando realizar conexión\n");

        // crear Socket para realizar la conexión con el servidor
        cliente = new Socket(InetAddress.getByName(servidorChat), 28001);

        // mostrar la información de la conexión
        mostrarMensaje("Conectado a: "
                + cliente.getInetAddress().getHostName());
//        System.out.println("Conectado a: "
//                + cliente.getInetAddress().getHostName());
    }

    // obtener flujos para enviar y recibir datos
    private void obtenerFlujos() throws IOException {
        // establecer flujo de salida para los objetos
        salida = new ObjectOutputStream(cliente.getOutputStream());
        salida.flush();
        entrada = new ObjectInputStream(cliente.getInputStream());

        mostrarMensaje("\nSe recibieron los flujos de E/S\n");
    }

    private void procesarConexion() throws IOException {
        establecerCampoTextoEditable(true);

        do {

            try {
                mensaje = (String) entrada.readObject();
                msg = mensaje;
                mostrarMensaje("\n" + mensaje);

                this.setChanged();
                this.notifyObservers();
            } catch (ClassNotFoundException excepcionClaseNoEncontrada) {
                JOptionPane.showMessageDialog(null, "Dato desconocido");
            }


        } while (!mensaje.equals("SERVIDOR>>> TERMINAR"));

    }

    private void cerrarConexion() {
        mostrarMensaje("\nCerrando conexión");
        establecerCampoTextoEditable(false);

        try {
            salida.close();
            entrada.close();
            cliente.close();
        } catch (IOException excepcionES) {
            JOptionPane.showMessageDialog(null, "Error al cerrar los flujos");
        }
    }

    public void enviarDatos(String mensaje) {
        try {
            salida.writeObject(mensaje);
            salida.flush();
            mostrarMensaje("\nCLIENTE>>> " + mensaje);
        } // procesar los problemas que pueden ocurrir al enviar el objeto
        catch (IOException excepcionES) {
            JOptionPane.showMessageDialog(null, "No se han eviado datos");
        }
    }

    // método utilitario que es llamado desde otros subprocesos para manipular a 
    // areaPantalla en el subproceso despachador de eventos
    private void mostrarMensaje(final String mensajeAMostrar) {
        // mostrar mensaje del subproceso de ejecución de la GUI
        SwingUtilities.invokeLater(
                new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
                    public void run() // actualiza areaPantalla
                    {
                    }
                } // fin de la clase interna
                ); // fin de la llamada a SwingUtilities.invokeLater
    }

    // método utilitario que es llamado desde otros subprocesos para manipular a 
    // campoIntroducir en el subproceso despachador de eventos
    private void establecerCampoTextoEditable(final boolean editable) {
        // mostrar mensaje del subproceso de ejecución de la GUI
        SwingUtilities.invokeLater(
                new Runnable() {  // clase interna para asegurar que la GUI se actualice apropiadamente
                    public void run() // establece la capacidad de modificar campoIntroducir
                    {
                        //campoIntroducir.setEditable( editable );
                    }
                } // fin de la clase interna
                ); // fin de la llamada a SwingUtilities.invokeLater
    }
// </editor-fold>         
}
